package com.shiku.imserver;

import com.shiku.imserver.service.IMBeanUtils;
import java.io.IOException;
import java.lang.management.ManagementFactory;
import java.lang.management.RuntimeMXBean;
import java.net.InetSocketAddress;
import java.net.StandardSocketOptions;
import java.nio.channels.AsynchronousChannelGroup;
import java.nio.channels.AsynchronousServerSocketChannel;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.TimeUnit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.tio.core.Node;
import org.tio.server.TioServer;
import org.tio.utils.date.DateUtils;
import org.tio.utils.hutool.StrUtil;

public class ShikuTioServer extends TioServer {
    private static Logger log = LoggerFactory.getLogger(ShikuTioServer.class);
    protected AsynchronousChannelGroup channelGroup = null;
    protected ImServerGroupContext serverGroupContext;
    private Node serverNode;
    protected AsynchronousServerSocketChannel serverSocketChannel;
    private AsynchronousServerSocketChannel wsServerSocketChannel;

    public ShikuTioServer(ImServerGroupContext serverGroupContext2) {
        super(serverGroupContext2);
        this.serverGroupContext = serverGroupContext2;
    }

    /* JADX DEBUG: Failed to find minimal casts for resolve overloaded methods, cast all args instead
     method: MutableMD:<T>:(java.net.SocketOption, java.lang.Object):java.nio.channels.AsynchronousServerSocketChannel throws java.io.IOException
     arg types: [java.net.SocketOption, boolean]
     candidates:
      ClspMth{java.nio.channels.AsynchronousServerSocketChannel.setOption(java.net.SocketOption, java.lang.Object):java.nio.channels.NetworkChannel throws java.io.IOException}
      MutableMD:<T>:(java.net.SocketOption, java.lang.Object):java.nio.channels.NetworkChannel throws java.io.IOException
      MutableMD:<T>:(java.net.SocketOption, java.lang.Object):java.nio.channels.AsynchronousServerSocketChannel throws java.io.IOException */
    /* JADX DEBUG: Failed to find minimal casts for resolve overloaded methods, cast all args instead
     method: MutableMD:<T>:(java.net.SocketOption, java.lang.Object):java.nio.channels.AsynchronousServerSocketChannel throws java.io.IOException
     arg types: [java.net.SocketOption, int]
     candidates:
      ClspMth{java.nio.channels.AsynchronousServerSocketChannel.setOption(java.net.SocketOption, java.lang.Object):java.nio.channels.NetworkChannel throws java.io.IOException}
      MutableMD:<T>:(java.net.SocketOption, java.lang.Object):java.nio.channels.NetworkChannel throws java.io.IOException
      MutableMD:<T>:(java.net.SocketOption, java.lang.Object):java.nio.channels.AsynchronousServerSocketChannel throws java.io.IOException */
    public void start(String serverIp, int serverPort) throws IOException {
        InetSocketAddress listenAddress;
        long start = System.currentTimeMillis();
        this.serverNode = new Node(serverIp, serverPort);
        this.channelGroup = AsynchronousChannelGroup.withThreadPool(this.serverGroupContext.groupExecutor);
        						
        this.serverSocketChannel = AsynchronousServerSocketChannel.open(this.channelGroup);
        this.serverSocketChannel.setOption(StandardSocketOptions.SO_REUSEADDR, true);
        this.serverSocketChannel.setOption(StandardSocketOptions.SO_RCVBUF, 65536);
       // this.serverSocketChannel.setOption(StandardSocketOptions.SO_REUSEADDR, (Object) true);
       // this.serverSocketChannel.setOption(StandardSocketOptions.SO_RCVBUF, (Object) 65536);
        if (StrUtil.isBlank(serverIp)) {
            listenAddress = new InetSocketAddress(serverPort);
        } else {
            listenAddress = new InetSocketAddress(serverIp, serverPort);
        }
        this.serverSocketChannel.bind(listenAddress, 0);
        this.wsServerSocketChannel = AsynchronousServerSocketChannel.open(this.channelGroup);
        this.wsServerSocketChannel.setOption(StandardSocketOptions.SO_REUSEADDR,true);
        this.wsServerSocketChannel.setOption(StandardSocketOptions.SO_RCVBUF, 65536);
        this.wsServerSocketChannel.bind(new InetSocketAddress(IMBeanUtils.getImconfig().getWsServerConfig().getBindPort().intValue()), 0);
        ShikuAcceptCompletionHandler acceptCompletionHandler = new ShikuAcceptCompletionHandler(this.serverSocketChannel, (byte) 1);
        ShikuAcceptCompletionHandler wsacceptCompletionHandler = new ShikuAcceptCompletionHandler(this.wsServerSocketChannel, (byte) 2);
        this.serverSocketChannel.accept(this, acceptCompletionHandler);
        this.wsServerSocketChannel.accept(this, wsacceptCompletionHandler);
        if (IMBeanUtils.getImconfig().isWebsocketSsl()) {
            try {
                this.serverGroupContext.useSsl(IMBeanUtils.getImconfig().getKeyStoreFile(), IMBeanUtils.getImconfig().getKeyStoreFile(), IMBeanUtils.getImconfig().getSslPassword());
            } catch (Exception e) {
                log.error(e.getMessage(), e);
            }
        }
        this.serverGroupContext.startTime = System.currentTimeMillis();
        IMBeanUtils.getBeanManager().startupAfter();
        int baseLen = "|----------------------------------------------------------------------------------------|".length();
        StackTraceElement[] ses = Thread.currentThread().getStackTrace();
        StackTraceElement se = ses[ses.length - 1];
        int aaLen = baseLen - 3;
        List<String> infoList = new ArrayList<>();
        infoList.add(StrUtil.fillAfter("GroupContext name", ' ', 18) + "| " + this.serverGroupContext.getName());
        infoList.add(StrUtil.fillAfter("Started at", ' ', 18) + "| " + DateUtils.formatDateTime(new Date()));
        infoList.add(StrUtil.fillAfter("Listen on", ' ', 18) + "| " + this.serverNode);
        infoList.add(StrUtil.fillAfter("Main Class", ' ', 18) + "| " + se.getClassName());
        try {
            RuntimeMXBean runtimeMxBean = ManagementFactory.getRuntimeMXBean();
            String pid = runtimeMxBean.getName().split("@")[0];
            infoList.add(StrUtil.fillAfter("Jvm start time", ' ', 18) + "| " + (System.currentTimeMillis() - runtimeMxBean.getStartTime()) + " ms");
            infoList.add(StrUtil.fillAfter("Tio start time", ' ', 18) + "| " + (System.currentTimeMillis() - start) + " ms");
            infoList.add(StrUtil.fillAfter("Pid", ' ', 18) + "| " + pid);
        } catch (Exception e2) {
        }
        String printStr = "\r\n" + "|----------------------------------------------------------------------------------------|" + "\r\n";
        Iterator<String> it = infoList.iterator();
        while (it.hasNext()) {
            printStr = printStr + "| " + StrUtil.fillAfter(it.next(), ' ', aaLen) + "|\r\n";
        }
        String printStr2 = printStr + "|----------------------------------------------------------------------------------------|" + "\r\n";
        if (log.isInfoEnabled()) {
            log.info(printStr2);
        } else {
            System.out.println(printStr2);
        }
    }

    public boolean stop() {
        boolean ret;
        setWaitingStop(true);
        boolean ret2 = true;
        try {
            this.channelGroup.shutdownNow();
        } catch (Exception e) {
            log.error("channelGroup.shutdownNow()时报错", e);
        }
        try {
            this.serverSocketChannel.close();
        } catch (Exception e1) {
            log.error("serverSocketChannel.close()时报错", e1);
        }
        try {
            this.serverGroupContext.groupExecutor.shutdown();
        } catch (Exception e12) {
            log.error(e12.toString(), e12);
        }
        try {
            this.serverGroupContext.tioExecutor.shutdown();
        } catch (Exception e13) {
            log.error(e13.toString(), e13);
        }
        this.serverGroupContext.setStopped(true);
        if (1 != 0) {
            try {
                if (this.serverGroupContext.groupExecutor.awaitTermination(6000, TimeUnit.SECONDS)) {
                    ret = true;
                    if (ret || !this.serverGroupContext.tioExecutor.awaitTermination(6000, TimeUnit.SECONDS)) {
                        ret2 = false;
                    } else {
                        ret2 = true;
                    }
                    log.info(this.serverNode + " stopped");
                    return ret2;
                }
            } catch (InterruptedException e2) {
                log.error(e2.getLocalizedMessage(), e2);
            }
        }
        ret = false;
        if (ret) {
        }
        ret2 = false;
        log.info(this.serverNode + " stopped");
        return ret2;
    }

    public AsynchronousServerSocketChannel getWsServerSocketChannel() {
        return this.wsServerSocketChannel;
    }

    public void setWsServerSocketChannel(AsynchronousServerSocketChannel wsServerSocketChannel2) {
        this.wsServerSocketChannel = wsServerSocketChannel2;
    }
}
